package com.yuw.reflections;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestDriver {
    public static void main(String[] args) {
        System.out.println("=======================");
        test01();
        System.out.println("=======================");
        test02();

    }

    /**
     * Filed类的使用、Method类
     */
    public static void test02() {
        // 获取Class的方式
        // 类名的.class
        Class<Student> clazz = Student.class;
        try {
            // 创建一个Student对象实例
            Student stu0 = new Student();
            System.out.println(stu0);

            // 获取Field属性的封装类
            Field field = clazz.getDeclaredField("stuName");
            // 设置可以访问私有属性
            field.setAccessible(true); // 可以访问私有属性
            field.set(stu0, "小明");
            System.out.println(stu0);

            System.out.println("***************************************");
            // 获取Student 类的 Method反射工具类
            Method method = clazz.getDeclaredMethod("doStuding",String.class);
            // 使用invoke调用获取的方法对象
            // 调用方法
            method.invoke(stu0, "tjise");

            System.out.println("等价于：");
            stu0.doStuding("tjise2");

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    /**
     * Class类的使用、Constructor类
     */
    public static void test01() {
        // 获取Class的方式
        // 类名的.class
        Class<Student> clazz = Student.class;
        // 通过Class的静态方法forName获取
        Class clazz1 = null;
        try {
            clazz1 = Class.forName("com.yuw.reflections.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 通过 实例对象的 getClass方法获取
        Student stu0 = new Student();
        Class clazz2 = stu0.getClass();

        // 创建这个被Class所描述的类的实例对象，这是绕开new构建一个类的实例对象的方式
        System.out.println(clazz == clazz2);
        System.out.println(clazz == clazz1);

        try {
            Student stu1 = clazz.newInstance();
            // 这里就通过Class反射获取了一个Student的实例对象
            stu1.setStuName("xiaoming");
            System.out.println(stu1);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        System.out.println("-------------构造方法----------------");
        try {
            // 获取构造方法对象： Student()
            Constructor<Student> constructor = clazz.getDeclaredConstructor();
            // 获取这个类的实例对象
            Student stu2 = constructor.newInstance();
            stu2.setStuName("xiaoming222");
            System.out.println(stu2);

            System.out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。");
            //  获取构造方法对象： Student(String stuName, String stuNum, int stuScore)
            Constructor<Student> constructor2 = clazz.getDeclaredConstructor(String.class, String.class, int.class);
            // 获取这个类的实例对象
            Student stu3 = constructor2.newInstance("小李", "10010", 20); // 参数列表和上面获取Constructor的参数列表保持一致
            System.out.println(stu3);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
